using System;
using System.Web.UI;
using System.Web.UI.Design;
using System.ComponentModel;
using System.Windows.Forms;
using System.ComponentModel.Design;
using System.Runtime.InteropServices;
using System.Reflection;

namespace NBusiness.Data.Web.Design
{

    /// <summary>
    /// Implements designer support for EntityDataSource.
    /// </summary>
    [ComVisible(false)]
    public class EntityDataSourceDesigner : DataSourceDesigner
    {
        private DataSourceControl _control;
        public DataSourceControl Control
        {
            get { return _control; }
        }

        // HACK: Basically we're doing dynamic typing here, it looks like an EntityDataSource but the Type's get screwed up somehow.
        /// <summary>
        /// Wrapping TypeName on _control with reflection calls since there is a bug in visual studio
        /// where it loads types and returns an error 'Invalid cast exception: cannot convert EntityDataSource into EntityDataSource'. 
        /// Very annoying...
        /// </summary>
        private PropertyInfo _typeNameProperty;
        internal string TypeName
        {
            get
            {
                if(_typeNameProperty == null)
                    _typeNameProperty = _control.GetType().GetProperty("TypeName");

                return (string)_typeNameProperty.GetValue(_control, null);
            }
            set
            {
                if (_typeNameProperty == null)
                    _typeNameProperty = _control.GetType().GetProperty("TypeName");

                _typeNameProperty.SetValue(_control, value, null);
            }
        }

        private PropertyInfo _assemblyNameProperty;
        internal string AssemblyName
        {
            get
            {
                if (_assemblyNameProperty == null)
                    _assemblyNameProperty = _control.GetType().GetProperty("AssemblyName");

                return (string)_assemblyNameProperty.GetValue(_control, null);
            }
            set
            {
                if (_assemblyNameProperty == null)
                    _assemblyNameProperty = _control.GetType().GetProperty("AssemblyName");

                _assemblyNameProperty.SetValue(_control, value, null);
            }
        }

        /// <summary>
        /// Initialize the designer component.
        /// </summary>
        /// <param name="component">The EntityDataSource control to 
        /// be designed.</param>
        public override void Initialize(IComponent component)
        {
            base.Initialize(component);
            _control = (DataSourceControl)component;
        }

        private EntityDesignerDataSourceView _View;
        /// <summary>
        /// Returns the default view for this designer.
        /// </summary>
        /// <param name="viewName">Ignored</param>
        /// <returns></returns>
        /// <remarks>
        /// This designer supports only a "Default" view.
        /// </remarks>
        public override DesignerDataSourceView GetView(string viewName)
        {
            if (_View == null)
            {
                _View = new EntityDesignerDataSourceView(
                    this,
                    viewName);
            }
            return _View;
        }

        public override bool CanConfigure
        {
            get
            {
                return true;
            }
        }
        public override void Configure()
        {
            EntityDataSourceConfiguration cfg = new EntityDataSourceConfiguration(_control, TypeName);
            if (cfg.ShowDialog() == DialogResult.OK && cfg.SelectedType != null)
            {
                string oldAssemblyName = AssemblyName;
                string oldTypeName = TypeName;

                AssemblyName = cfg.SelectedType.Assembly.FullName;
                TypeName = cfg.SelectedType.ToString();
                PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(cfg.SelectedType);

                PropertyDescriptor typename = properties.Find("TypeName", false);
                RaiseComponentChanging(typename);
                RaiseComponentChanged(typename,
                    oldTypeName,
                    TypeName);

                PropertyDescriptor assemblyname = properties.Find("AssemblyName", false);
                RaiseComponentChanging(assemblyname);
                RaiseComponentChanged(assemblyname,
                    oldAssemblyName,
                    AssemblyName);

            }
        }

        /// <summary>
        /// Return a list of available views.
        /// </summary>
        /// <remarks>
        /// This designer supports only a "Default" view.
        /// </remarks>
        public override string[] GetViewNames()
        {
            return new string[] { "Default" };
        }

        /// <summary>
        /// Refreshes the schema for the data.
        /// </summary>
        /// <param name="preferSilent"></param>
        /// <remarks></remarks>
        public override void RefreshSchema(bool preferSilent)
        {
            this.OnSchemaRefreshed(EventArgs.Empty);
        }

        /// <summary>
        /// Get a value indicating whether the control can
        /// refresh its schema.
        /// </summary>
        public override bool CanRefreshSchema
        {
            get { return true; }
        }

        /// <summary>
        /// Get a value indicating whether the control can
        /// be resized.
        /// </summary>
        public override bool AllowResize
        {
            get { return false; }
        }
    }
}
